function RateLimit(ply)
	if(ply.RateLimit == nil) then ply.RateLimit = CurTime() return true end
	if(ply.RateLimit + 0.5 > CurTime()) then return false end
	if(ply.RateLimit + 0.5 < CurTime()) then ply.RateLimit = CurTime() return true end
end

function Upgrade(ply, cmd, args)
    local tr = ply:GetEyeTraceNoCursor()
    local ent = tr.Entity
    
    if ent:GetPos():Distance(ply:GetPos()) < 256 then
		if ent.Base == "base_structure" && ent.dt.Owner == ply then
			if ent.Upgrades then
				if(ply:CanAfford(ent.Cost * (ent.dt.Upgrade + 1))) then
					if ent.dt.Upgrade < #ent.Upgrades then
						ply:TakeMoney(ent.Cost * (ent.dt.Upgrade + 1))
						ent.dt.Upgrade = ent.dt.Upgrade + 1
						Notify(ply, 0, 3, "Applying level ".. ent.dt.Upgrade .. " upgrade to your " .. ent.PrintName) 
						//we get all the variables in the ent upgrade table we want to change, and set them.
						for k, v in pairs(ent.Upgrades[ent.dt.Upgrade]) do
							ent[k] = v
						end
						//we check if ENT:UpgradeCallback(level) exists, and if we do, then we call it with the upgrade level. This is if we want to trigger something on the entity when its upgraded. 
						if(ent.UpgradeCallback ~=nil) then
							ent:UpgradeCallback(ent.dt.Upgrade)
						end
					else
						if(!RateLimit(ply)) then return end
						Notify(ply, 4, 3, "Structure is at the maximum upgrade level!")
					end
				end
			else
				if(!RateLimit(ply)) then return end
				Notify(ply, 4, 3, "You cannot upgrade that structure!")
			end
		else
			if(!RateLimit(ply)) then return end
			Notify(ply, 4, 3, "You can only upgrade your own structures!")
		end
    end
end
concommand.Add("rpdm_upgrade", Upgrade)

function ChangeClass(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local class = team.GetClass(tonumber(args[1]))
	local curclass = ply.Class
	
	if curclass == class then
		Notify(ply, 4, 4, string.format("You are already %s.", class.Name))
	elseif class.MaxAmount && team.NumPlayers(class.TeamIndex) >= class.MaxAmount then
		Notify(ply, 4, 4, string.format("Maximum amount of %ss reached!", name))
	elseif class.PrereqClass && curclass.Name != class.PrereqClass then
		Notify(ply, 4, 4, string.format("Must be %s to go %s.", class.PrereqClass, class.Name))
	elseif class.ReqTime && (CurTime() - ply.classtime) < class.ReqTime then
		Notify(ply, 4, 4, string.format("Must be %s for %i more seconds to be %s", curclass.Name, class.ReqTime - math.floor(CurTime() - ply.classtime), class.Name))
	else
		ply:SetTeam(class.TeamIndex)
		ply.Class = ply:GetTeamClass()
		ply:SetNWString("job", class.Name)
		local vPoint = ply:GetShootPos() + Vector(0, 0, 50)
		local effectdata = EffectData()
			effectdata:SetEntity(ply)
			effectdata:SetStart(vPoint)
			effectdata:SetOrigin(vPoint)
			effectdata:SetScale(1)
		util.Effect("entity_remove", effectdata)
		GAMEMODE:PlayerSetModel(ply)
		GAMEMODE:PlayerLoadout(ply)
		ply.classtime = CurTime()
		timer.Create(ply:UniqueID() .. "jobtimer", 60/*pay day time*/, 0, ply.GiveMoney, ply, class.Pay)
	end
end
concommand.Add("rpdm_changeclass", ChangeClass)

//all of these functions can be merged into rpdm_buysent and rpdm_buyweapon, ill do that later.
function BuySent(ply, cmd, args)
	debug.Trace()
	if(!RateLimit(ply)) then return end
	local sentclass = args[1]
	local sent = scripted_ents.Get(sentclass)
	if sent && sent.Base == "base_structure" then
		if(sent.MaxStructs <= ply:StructCount(sentclass)) then Notify(ply, 4, 3, "You have the limit of " .. sent.PrintName ) return end
		if(!ply:CanAfford(sent.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		sent:SpawnFunction(ply, tr)
		ply:TakeMoney(sent.Cost)
		Notify(ply, 0, 3, "You bought a " .. sent.PrintName)
	end
end
concommand.Add("rpdm_buysent", BuySent)

function BuyWeapon(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local wepclass = args[1]
	local weptable = weapons.Get(wepclass)
	if weptable && (weptable.Pistol || weptable.Other) && weptable.Spawnable then
		if(!ply:CanAfford(weptable.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		local weapon = ents.Create(wepclass)
		weapon:SetPos(tr.HitPos)
		weapon:Spawn()
		ply:TakeMoney(weptable.Cost)
		Notify(ply, 0, 3, "You bought a " .. weptable.PrintName)
	end
end
concommand.Add("rpdm_buyweapon", BuyWeapon)

//the weapons should spawn in a line parallel with the player's two eyes every time (it currently doesn't)
function BuyWeaponShipment(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local wepclass = args[1]
	local weptable = weapons.Get(wepclass)
	if weptable && (weptable.Sniper || weptable.Rifle || weptable.Shotgun) && weptable.Spawnable then
		if(!ply:CanAfford(weptable.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		for i = -5, 5, 1 do
			local weapon = ents.Create(wepclass)
			weapon:SetPos(Vector(tr.HitPos.x, tr.HitPos.y + (i * 10), tr.HitPos.z))
			weapon:Spawn()
		end
		ply:TakeMoney(weptable.Cost)
		Notify(ply, 0, 3, "You bought shipment of " .. weptable.PrintName)
	end
end
concommand.Add("rpdm_buyweaponshipment", BuyWeaponShipment)

function BuyGrenadeShipment(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local wepclass = args[1]
	local weptable = weapons.Get(wepclass)
	if weptable && weptable.Grenade && weptable.Spawnable then
		if(!ply:CanAfford(weptable.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		for i = -2, 1, 1 do
			local weapon = ents.Create(wepclass)
			weapon:SetPos(Vector(tr.HitPos.x, tr.HitPos.y + (i * 10), tr.HitPos.z))
			weapon:Spawn()
		end
		
		ply:TakeMoney(100)
		Notify(ply, 0, 3, "You bought a shipment of " .. weptable.PrintName)
	end
end
concommand.Add("rpdm_buygrenadeshipment", BuyGrenadeShipment)

function BuyDrugShipment(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local drugclass = args[1]
	local drug = scripted_ents.Get(drugclass)
	if drug && drug.Base == "base_drug" && drug.Spawnable then
		if(!ply:CanAfford(drug.Cost * 5)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		for i = -2, 2, 1 do
			local drug = ents.Create(drugclass)
			drug:SetPos(Vector(tr.HitPos.x, tr.HitPos.y + (i * 10), tr.HitPos.z))
			drug:Spawn()
		end

		ply:TakeMoney(drug.Cost * 5)
		Notify(ply, 0, 3, "You bought a shipment of " .. drug.PrintName)
	end
end
concommand.Add("rpdm_buydrugshipment", BuyDrugShipment)

function BuyItem(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local itemclass = args[1]
	local item = scripted_ents.Get(itemclass)
	if item && item.Base == "base_item" && item.Spawnable then
		if(!ply:CanAfford(item.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		item:SpawnFunction(ply, tr)
		ply:TakeMoney(item.Cost)
		Notify(ply, 0, 3, "You bought a " .. item.PrintName)
	end
end
concommand.Add("rpdm_buyitem", BuyItem)

function BuyAmmo(ply, cmd, args)
	if(!RateLimit(ply)) then return end
	local ammoclass = args[1]
	local ammo = scripted_ents.Get(ammoclass)
	if ammo && ammo.Base == "base_ammo" && ammo.Spawnable then
		if(!ply:CanAfford(ammo.Cost)) then Notify(ply, 4, 3, "You cannod afford that!") return end
		local trace = {}
			trace.start = ply:EyePos()
			trace.endpos = trace.start + ply:GetAimVector() * 85
			trace.filter = ply	
		local tr = util.TraceLine(trace)
		
		ammo:SpawnFunction(ply, tr)
		ply:TakeMoney(ammo.Cost)
		Notify(ply, 0, 3, "You bought " .. ammo.PrintName .. " Ammo")
	end
end
concommand.Add("rpdm_buyammo", BuyAmmo)